package com.hx.netty.chat.server.processor;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.hx.netty.chat.protocol.IMP;
import com.hx.netty.chat.protocol.ImDecoder;
import com.hx.netty.chat.protocol.ImEncoder;
import com.hx.netty.chat.protocol.ImMsg;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * @author Huathy
 * @date 2021-10-28 22:28
 * @description 处理中心
 */
@SuppressWarnings("all")
public class MsgProcessor {

    // 在线用户组。做了优化的。netty的channelGroup是set，对线程安全、性能等做了处理。也可以用map或list代替。
    private static ChannelGroup onlineUsers = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    ;

    // 定义一些扩展属性
    private static final AttributeKey<String> NICK_NAME = AttributeKey.valueOf("nickName");
    private static final AttributeKey<String> IP_ADDR = AttributeKey.valueOf("ipAddr");
    private static final AttributeKey<JSONObject> ATTRS = AttributeKey.valueOf("attrs");
    private static final AttributeKey<String> FROM = AttributeKey.valueOf("from");

    private ImDecoder decoder = new ImDecoder();
    private ImEncoder encoder = new ImEncoder();


    public void process(Channel client, ImMsg msg) {
        process(client, encoder.encode(msg));
    }

    public void process(Channel client, String msg) {
        // 统一在这里处理逻辑
        ImMsg req = decoder.decode(msg);
        if (ObjectUtil.isNull(req)) {
            return;
        }
        if (req.getCmd().equals(IMP.LOGIN.getName())) {
            // 保存用户IP地址、端口、昵称、终端类型、
            client.attr(NICK_NAME).getAndSet(req.getSender());
            client.attr(IP_ADDR).getAndSet(getAddress(client));
            client.attr(FROM).getAndSet(req.getTerminal());
            // 把这个用户保存到统一的容器中，要给所有在线用户推送消息
            onlineUsers.add(client);
            //通知到所有在线用户，XX上线了
            for (Channel channel : onlineUsers) {
                boolean isself = (channel == client);
                //是自己则建立连接，否则通知XX上线
                req = new ImMsg(IMP.SYSTEM.getName(), sysTime(), onlineUsers.size(), isself ? "已与服务器建立连接.." : getNickName(client) + "加入");

                //消息准备完毕，开始推送消息
                //如果终端是控制台，开始推送ImMsg
                if ("Consule".equals(channel.attr(FROM).get())) {
                    channel.writeAndFlush(req);
                    continue;
                }
                //如果终端是
                String content = encoder.encode(req);
                channel.writeAndFlush(new TextWebSocketFrame(content));
            }
        } else if (req.getCmd().equals(IMP.CHAT.getName())) {
            for (Channel channel : onlineUsers) {
                boolean isself = (channel == client);
                req.setSender(isself ? "you" : getNickName(client));
                req.setTime(sysTime());
                //如果终端是控制台，开始推送ImMsg
                if ("Consule".equals(channel.attr(FROM).get())) {
                    channel.writeAndFlush(req);
                    continue;
                }
                //如果终端是
                String content = encoder.encode(req);
                channel.writeAndFlush(new TextWebSocketFrame(content));
            }
        } else if (req.getCmd().equals(IMP.FLOWER.getName())) {
            JSONObject attrs = getAttrs(client);
            long currTime = sysTime();
            // 属于权限
            // 可以加一个专门处理权限的handler
            if(null != attrs){
                long lastTime = attrs.getLongValue("lastFlowerTime");
                //60秒之内不允许重复刷鲜花
                int secends = 10;
                long sub = currTime - lastTime;
                if(sub < 1000 * secends){
                    req.setSender("you");
                    req.setCmd(IMP.SYSTEM.getName());
                    req.setContent("您送鲜花太频繁," + (secends - Math.round(sub / 1000)) + "秒后再试");

                    String content = encoder.encode(req);
                    client.writeAndFlush(new TextWebSocketFrame(content));
                    return;
                }
            }

            //正常送花
            for (Channel channel : onlineUsers) {
                if (channel == client) {
                    req.setSender("you");
                    req.setContent("你给大家送了一波鲜花雨");
                    setAttrs(client, "lastFlowerTime", currTime);
                }else{
                    req.setSender(getNickName(client));
                    req.setContent(getNickName(client) + "送来一波鲜花雨");
                }
                req.setTime(sysTime());
                // 只有web页面支持刷花
                String content = encoder.encode(req);
                channel.writeAndFlush(new TextWebSocketFrame(content));
            }
        }
    }

    /**
     * 获取用户昵称
     *
     * @param client
     * @return
     */
    public String getNickName(Channel client) {
        return client.attr(NICK_NAME).get();
    }

    /**
     * 获取用户远程IP地址
     *
     * @param client
     * @return
     */
    public String getAddress(Channel client) {
        return client.remoteAddress().toString().replaceFirst("/", "");
    }

    /**
     * 获取扩展属性
     *
     * @param client
     * @return
     */
    public JSONObject getAttrs(Channel client) {
        try {
            return client.attr(ATTRS).get();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取系统时间
     *
     * @return
     */
    private Long sysTime() {
        return System.currentTimeMillis();
    }


    /**
     * 获取扩展属性
     * @param client
     * @return
     */
    private void setAttrs(Channel client,String key,Object value){
        try{
            JSONObject json = client.attr(ATTRS).get();
            json.put(key, value);
            client.attr(ATTRS).set(json);
        }catch(Exception e){
            JSONObject json = new JSONObject();
            json.put(key, value);
            client.attr(ATTRS).set(json);
        }
    }
}
